﻿using ImageProcess;
using ImageProcess.Common.Model;
using project.B12.IRepository;
using project.B12.IService;
using project.B12.Model.Models;
using System.Drawing;
using System.Runtime.Versioning;

namespace sproject.B12.Service
{

    /// <summary>
    /// 图像算法分析
    /// </summary>
    public class ServiceIdentification: IServiceIdentification
    {
        public IConfigurationFileManagement configurationFileManagement;
        public IMICPlateMes mICPlateMes;
        public IBacteriaRepository bacteriaRepository;
        public ServiceIdentification(IConfigurationFileManagement _configurationFileManagement, 
            IMICPlateMes _mICPlateMes,
            IBacteriaRepository _bacteriaRepository)
        {
            configurationFileManagement = _configurationFileManagement;
            mICPlateMes = _mICPlateMes;
            bacteriaRepository = _bacteriaRepository;
        }

        [SupportedOSPlatform("windows")]
        public ResultMes[] Identification_All(string DirectoryName,string plateStyle, string bacterialName, Action<string> progressCallback)
        {
            if (string.IsNullOrEmpty(DirectoryName))
            {
                //MessageBox.Show("文件路径错误"); return;
            }
            else
            {
                if (!Directory.Exists(DirectoryName))
                {
                    //MessageBox.Show("文件夹不存在");
                    //return;
                }
            }
            var mf = mICPlateMes.microplateAntibioticConcentrationMes.Find(p => p.name == plateStyle);
            if (mf == null)
            {
                throw new Exception("配置文件错误");
            }
            var map = configurationFileManagement.GetMapCfgByName(mf.Map);
            Read read;
            var barlists = bacteriaRepository.QueryByCNName(bacterialName);

            if (barlists != null && barlists.Count > 0)
            {
                read = configurationFileManagement.GetReadCfgByName(barlists.First().Read);
            }
            else
            {
                throw new Exception("Bacteria not found");
            }

            int R = map.R;
            int grayValueCo = read.grayValueCo;
            int PixelCo = read.PixelCo;
            float CVCo = read.CVCo;
            int width = map.Square;
            int height = map.Square;

            HollowBubbleARecognition BubbleErase = new HollowBubbleARecognition();
            BubbleErase.SetFilterWhiteBlockArea(1, 200);
            BubbleErase.SetFenceFilterCase1(100, 1, 0.025f, 1500);
            BubbleErase.SetDealArea(160, 160, new Dot(80, 80), 62);

            DirectoryInfo directoryInfo = new DirectoryInfo(DirectoryName);
            int totalPics = directoryInfo.GetFiles("*.jpg").Length;
            ResultMes[] ret = new ResultMes[totalPics];
            for (int i = 0; i < totalPics; i++)
            {
                progressCallback(i.ToString()+'/'+ totalPics.ToString());
                try
                {
                    //去气泡
                    BubbleErase.AutoRoundDeal(new Bitmap(Path.Combine(DirectoryName, $"{i + 1}.jpg")), 100);
                    //Image img0 = Image.FromFile(Path.Combine(DirectoryName, $"{i + 1}.jpg"));
                   // map0.Save(Path.Combine(DirectoryName+"xx", $"{i + 1}.jpg"), ImageFormat.Jpeg);
                    Bitmap map0 = BubbleErase.mBitmapOriginal;
                    //map0.Save(Path.Combine(DirectoryName + "xx", $"{i + 1}.jpg"), ImageFormat.Jpeg);
                    ret[i] = Algorithm(map0, width, height, R, CVCo, PixelCo, grayValueCo);
                    //img0.Dispose();
                }
                catch
                {
                    ret[i].ret = "/";
                    //TODO 打开孔位 图片失败
                }
                try
                {
                    int AI = 0;
                    string ai = "";
                    //AlgorithmAI(Path.Combine(DirectoryName, $"{i + 1}.jpg"), ref AI, ref ai);
                    ret[i].ai = ai;
                    ret[i].ret += $"/{AI}";
                }
                catch 
                {
                    ret[i].ret += "/";
                }
            }
            return ret;
        }

        [SupportedOSPlatform("windows")]
        public ResultMes[] Identification_Speciall(string DirectoryName, string plateStyle, Dictionary<string, List<int>> bacterialNames, bool isColumn, Action<string> progressCallback)
        {
            var mf = mICPlateMes.microplateAntibioticConcentrationMes.Find(p => p.name == plateStyle);
            if (mf == null)
            {
                throw new Exception("配置文件错误");
            }
            var map = configurationFileManagement.GetMapCfgByName(mf.Map);
            Dictionary<string,List<int>> bacteriaIndex = new Dictionary<string, List<int>>();
            foreach (var item in bacterialNames)
            {
                List<int> indexes = new List<int>();
                bacteriaIndex.Add(item.Key, indexes);
                foreach (var value in item.Value)
                {
                    if (isColumn)
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            int index = i * 12 + value - 1;
                            bacteriaIndex[item.Key].Add(index);
                        }
                    }
                    else
                    {
                        for(int i = 0;i<12;i++)
                        {
                            int index = (value-1) * 12 + i;
                            bacteriaIndex[item.Key].Add(index);
                        }
                    }
                }
            }
            DirectoryInfo directoryInfo = new DirectoryInfo(DirectoryName);
            int totalPics = directoryInfo.GetFiles("*.jpg").Length;
            ResultMes[] ret = new ResultMes[totalPics];

            foreach (var bacteriaName in bacteriaIndex)
            {
                Read read;
                var barlists = bacteriaRepository.QueryByCNName(bacteriaName.Key);
                if (barlists != null && barlists.Count > 0)
                {
                    read = configurationFileManagement.GetReadCfgByName(barlists.First().Read);
                }
                else
                {
                    throw new Exception("Bacteria not found");
                }
                int R = map.R;
                int grayValueCo = read.grayValueCo;
                int PixelCo = read.PixelCo;
                float CVCo = read.CVCo;
                int width = map.Square;
                int height = map.Square;

                HollowBubbleARecognition BubbleErase = new HollowBubbleARecognition();
                BubbleErase.SetFilterWhiteBlockArea(1, 200);
                BubbleErase.SetFenceFilterCase1(100, 1, 0.025f, 1500);
                BubbleErase.SetDealArea(160, 160, new Dot(80, 80), 62);

                foreach(var index in bacteriaName.Value)
                {
                    progressCallback(index.ToString() + '/' + totalPics.ToString());
                    try
                    {
                        //去气泡
                        BubbleErase.AutoRoundDeal(new Bitmap(Path.Combine(DirectoryName, $"{index + 1}.jpg")), 100);
                        Bitmap map0 = BubbleErase.mBitmapOriginal;
                        ret[index] = Algorithm(map0, width, height, R, CVCo, PixelCo, grayValueCo);
                    }
                    catch
                    {
                        ret[index].ret = "/";
                        //TODO 打开孔位 图片失败
                    }
                    try
                    {
                        int AI = 0;
                        string ai = "";
                        //AlgorithmAI(Path.Combine(DirectoryName, $"{i + 1}.jpg"), ref AI, ref ai);
                        ret[index].ai = ai;
                        ret[index].ret += $"/{AI}";
                    }
                    catch
                    {
                        ret[index].ret += "/";
                    }
                }
            }
            return ret;
        }

        #region
        //[SupportedOSPlatform("windows")]
        //public void Identification_AI_All(string DirectoryName,ref List<int?>AI, ref List<string> ai)
        //{
        //    DirectoryInfo directoryInfo = new DirectoryInfo(DirectoryName);
        //    int totalPics = directoryInfo.GetFiles("*.jpg").Length;
        //    for (int i = 0; i < totalPics; i++)
        //    {
        //        try
        //        {
        //            int _AI = 0;
        //            string _ai = "";
        //            //AlgorithmAI(Path.Combine(DirectoryName, $"{i + 1}.jpg"), ref _AI, ref _ai);
        //            AI.Add(_AI);
        //            ai.Add(_ai);
        //        }
        //        catch
        //        {
        //            AI.Add(null);
        //            ai.Add("");
        //        }
        //    }
        //}
        //[SupportedOSPlatform("windows")]
        //public string Identification_single(string DirectoryName,int indexHole,uint plateStyle)
        //{
        //    if (string.IsNullOrEmpty(DirectoryName))
        //    {
        //        //MessageBox.Show("文件路径错误"); return;
        //    }
        //    else
        //    {
        //        if (!Directory.Exists(DirectoryName))
        //        {
        //            //MessageBox.Show("文件夹不存在"); return;
        //        }
        //    }
        //    int R = int.Parse(iniUtil.INIRead("Algorithm", "R", getPlateConf(plateStyle)));
        //    int grayValueCo = int.Parse(iniUtil.INIRead("Algorithm", "grayValueCo", getPlateConf(plateStyle)));
        //    int PixelCo = int.Parse(iniUtil.INIRead("Algorithm", "PixelCo", getPlateConf(plateStyle)));
        //    float CVCo = float.Parse(iniUtil.INIRead("Algorithm", "CVCo", getPlateConf(plateStyle)));
        //    int width = int.Parse(iniUtil.INIRead("cut", "width", getPlateConf(plateStyle)));
        //    int height = int.Parse(iniUtil.INIRead("cut", "height", getPlateConf(plateStyle)));
        //    string ret = "";
        //    try
        //    {
        //        Image img0 = Image.FromFile(Path.Combine(DirectoryName, $"{indexHole + 1}.jpg"));
        //        Bitmap map0 = new Bitmap(img0);
        //        ret = Algorithm(map0, width, height, R, CVCo, PixelCo, grayValueCo);
        //        ret+="/"; //TODO  AI fa
        //        img0.Dispose();
        //    }
        //    catch
        //    {
        //        //TODO 打开孔位 图片失败
        //    }
        //    return ret;
        //}
        #endregion

        [SupportedOSPlatform("windows")]
        private ResultMes Algorithm(Bitmap holeMap, int width, int height, int R, float CVCo, int PixelCo, int grayValueCo)
        {
            List<int> listPix = new List<int>();
            ResultMes retMes= new ResultMes();
            int retINT1 = 0;
            int retINT2 = 0;
            for (int i = 0; i < holeMap.Height; i++)
            {
                for (int j = 0; j < holeMap.Width; j++)
                {
                    if (inR(j, i, width / 2, height / 2, R))
                    {
                        listPix.Add(getHoleHD(holeMap, j, i));
                    }
                }
            }
            if (listPix.Count > 1)
            {
                var junzhi = listPix.Average();
                var biaozuncha = CalculateStdDev(listPix, junzhi);
                var cv = biaozuncha / junzhi;
                retMes.ave = junzhi.ToString("F0"); retMes.cv = cv.ToString("0.000");

                retMes.max = listPix.Max().ToString();
                retMes.min = listPix.Min().ToString();
                if (cv > 0.4)
                {
                    retINT1 = 9;

                }
                else if (cv > 0.35)
                {
                    retINT1 = 8;

                }
                else if (cv > 0.3)
                {
                    retINT1 = 7;

                }
                else if (cv > 0.25)
                {
                    retINT1 = 6;

                }
                else if (cv > 0.2)
                {
                    retINT1 = 5;

                }
                else if (cv > CVCo)
                {

                    retINT1 = 4;
                }
                else if (cv > 0.05)
                {
                    retINT1 = 3;

                }
                else if (cv > 0.03)
                {
                    retINT1 = 2;

                }
                else if (cv > 0.01)
                {
                    retINT1 = 1;

                }
                else
                {
                    retINT1 = 0;
                }
            }
            int count = listPix.Count(p => p <= grayValueCo);
            retMes.cnt = count.ToString();
            if (count > PixelCo * 3.5)
            {
                retINT2 = 9;
            }
            else if (count > PixelCo * 3.0)
            {
                retINT2 = 8;
            }
            else if (count > PixelCo * 2.5)
            {
                retINT2 = 7;
            }
            else if (count > PixelCo * 2.0)
            {
                retINT2 = 6;
            }
            else if (count > PixelCo * 1.5)
            {
                retINT2 = 5;
            }
            else if (count > PixelCo * 1.0)
            {
                retINT2 = 4;
            }
            else if (count > PixelCo * 0.5)
            {
                retINT2 = 3;
            }
            else if (count > PixelCo * 0.3)
            {
                retINT2 = 2;
            }
            else if (count > PixelCo * 0.1)
            {
                retINT2 = 1;
            }
            else
            {
                retINT2 = 0;
            }
            retMes.ret = $"{retINT2}/{retINT1}";
            return retMes;
        }


        //private void AlgorithmAI(string filePath,ref int AI,ref string ai)
        //{
        //    var imageBytes = File.ReadAllBytes(filePath);
        //    MLModel1.ModelInput sampleData = new MLModel1.ModelInput()
        //    {
        //        ImageSource = imageBytes,
        //    };
        //    var result = MLModel1.Predict(sampleData);
        //    if (result != null && result.Score.Length == 2)
        //    {
        //        int xx = configurationFileManagement.InstrumentConf.key;
        //        ai = result.Score[xx].ToString("F3");
        //        if (result.Score[xx] >0.99)
        //        {
        //            AI = 9;
        //        }
        //        else if (result.Score[xx] > 0.9)
        //        {
        //            AI = 8;
        //        }
        //        else if (result.Score[xx] > 0.8)
        //        {
        //            AI = 7;
        //        }
        //        else if (result.Score[xx] > 0.7)
        //        {
        //            AI = 6;
        //        }
        //        else if (result.Score[xx] > 0.6)
        //        {
        //            AI = 5;
        //        }
        //        else if (result.Score[xx] > 0.5)
        //        {
        //            AI = 4;
        //        }
        //        else if (result.Score[xx] > 0.4)
        //        {
        //            AI = 3;
        //        }
        //        else if (result.Score[xx] > 0.3)
        //        {
        //            AI = 2;
        //        }
        //        else if (result.Score[xx] > 0.1)
        //        {
        //            AI = 1;
        //        }
        //        else
        //        {
        //            AI = 0;
        //        }
        //    }
        //}
        private bool inR(int x, int y, int cenX, int cenY, int R)
        {
            double r = Math.Sqrt((x - cenX) * (x - cenX) + (y - cenY) * (y - cenY));
            return r <= R;
        }
        [SupportedOSPlatform("windows")]
        private byte getHoleHD(Bitmap holemap, int x, int y)
        {
            if (holemap != null)
            {
                Color rgb = holemap.GetPixel(x, y);
                return (byte)((rgb.R + rgb.G + rgb.B) / 3);
            }
            else
                return 0;
        }
        private double CalculateStdDev(List<int> values, double avg)
        {
            if (values.Count == 0)
                return 0;

            var sum = values.Sum(d => Math.Pow(d - avg, 2));
            return Math.Sqrt(sum / (values.Count() - 1));
        }
        private string getPlateConf(uint plateID)
        {
            return Path.Combine("conf", $"Microplate_{plateID}.ini");
        }

      
    }
}
